# predictor.py
import cv2
import numpy as np
from PIL import Image
import config as cfg
#from control import Control
from DataHandler import DataHandler
from threading import Thread
from flask1.app import Web
from model_loader import ModelLoader
import time


#plat = Control()
dh = DataHandler()
web = Web()
#fd = FullDetect()

class Predictor:
    def __init__(self, model_dir):
        self.predictor = ModelLoader.load_model(model_dir)
        self.cap = cv2.VideoCapture(0)
        self.cap.set(3, 1920)
        self.cap.set(4, 1080)

    def Predict(self, image):
        # image = Image.fromarray(cv2.cvtColor(image, cv2.COLOR_BGRA2RGB))
        h, w = image.shape[:2]
        # image = cv2.cvtColor(image,cv2.COLOR_BGR2RGB) # opencv读入的图片属性是BGR格式的 转换成RGB格式
        # print(h,w)
        # 定义裁剪区域的坐标
        x1, y1 = 590, 150  # 左上角坐标
        x2, y2 = x1 + 1080, y1 + 530  # 右下角坐标

        # 裁剪图像
        image = image[y1:y2, x1:x2]

        base_img = cv2.resize(image, cfg.target_size)

        h, w = base_img.shape[:2]
        # print(h,w)

        img = self.Preprocess(base_img)      
        img_tensor = self.predictor.get_input(1)  # 1

        image_data = np.array(img).flatten().tolist()
        img_tensor.resize([1, 3, cfg.target_size[0], cfg.target_size[1]])
        img_tensor.set_float_data(image_data)

        scale_tensor = self.predictor.get_input(2)
        scale_tensor.resize([1, 2])
        scale_tensor.set_float_data(
            np.array([w / cfg.target_size[0], h / cfg.target_size[1]]).astype(
                'float32').reshape(1, 2).flatten().tolist())
        #
        shape_tensor = self.predictor.get_input(0)
        shape_tensor.resize([1, 2])
        shape_tensor.set_float_data(
            np.array([w, h]).astype('float32').reshape([1, 2]).flatten().tolist())
        # print("1")
        self.predictor.run()
        # print("2")
        # output_tensor_1 = self.predictor.get_output(1) # 被保留下来的索引,暂时未知，不知道有啥用
        output_tensor_0 = self.predictor.get_output(0)

        res_0 = output_tensor_0.float_data()
        # res_1 = output_tensor_1.int32_data()

        return res_0, base_img
        # ,res_1

    @staticmethod
    def Preprocess(img):
        # img = img.resize(input_image_size, Image.BILINEAR)
        # if img.mode != 'RGB':
        #    img = img.convert('RGB')
        # 图片已经转换成numpy的格式
        img = np.array(img).astype('float32').transpose((2, 0, 1))  # HWC to CHW
        mean = np.array(cfg.mean)
        std = np.array(cfg.std)
        img /= 255.0
        img -= mean[:, np.newaxis, np.newaxis]
        img /= std[:, np.newaxis, np.newaxis]
        img = img[np.newaxis, :]
        return img

    def draw(self, image, bbox, start_time, j, label_time):
        # 省略部分代码...




        label_true = "None"  # 初始化label_true为 "None"
        label = "None"  # 初始化label为 "None"
        label_counts = {}  # 用于跟踪标签出现的次数的字典
        max_center_count = {}


        center_x = 0
        center_y = 0
        is_there_object = 0

        # 设置不检测物体时长
        timeout = cfg.timeout
        elapsed_time = time.time() - start_time

        print("闲置时间：" + str(elapsed_time))
        # 循环遍历检测框信息

        if elapsed_time >= timeout:
            is_there_object = 1
            start_time = time.time()

        # 新增的变量，用于记录物体数量
        num_detected_objects = 0

        for i in range(0, len(bbox), 6):

            info = bbox[i:i + 6]  # 获取当前检测框的信息
            label = cfg.label_map[info[0]]  # 获取标签名称
            (text_width, text_height) = cv2.getTextSize(label, cv2.FONT_HERSHEY_SIMPLEX, 0.5, 1)[0]
            background = cfg.color_map[info[0]]
            score = info[1]  # 获取置信度分数

            # print(is_there_object)

            # 如果置信度分数低于设定的阈值，跳过当前检测框
            if float(score) < cfg.threshold:
                continue
            start_time = time.time()

            x1 = int(info[2])  # 获取检测框左上角x坐标
            x2 = int(info[4])  # 获取检测框右下角x坐标
            y1 = int(info[3])  # 获取检测框左上角y坐标
            y2 = int(info[5])  # 获取检测框右下角y坐标

            center_x = (x1 + x2) / 2
            center_y = (y1 + y2) / 2
            print(f'bbox:{x1, y1, x2, y2},label:{label},scores:{score}')

            image = cv2.rectangle(image, (x1, y1), (x2, y2),
                                  background, 2)
            if y1 < text_height:  # 在图片框内写
                image = cv2.rectangle(image, (x1, y1), (x1 + text_width, y1 + text_height), color=background,
                                      thickness=-1)
                image = cv2.putText(image, label, (x1, y1 + text_height), cv2.FONT_HERSHEY_SIMPLEX, 0.5,
                                    (0, 0, 0), 1)

            else:  # 在图片框外写
                image = cv2.rectangle(image, (x1, y1 - text_height), (x1 + text_width, y1), color=background,
                                      thickness=-1)
                image = cv2.putText(image, label, (x1, y1), cv2.FONT_HERSHEY_SIMPLEX, 0.5,
                                    (0, 0, 0), 1)

            # 在标签计数字典中增加或更新标签出现的次数
            if label in label_counts:
                label_counts[label] += 1
            else:
                label_counts[label] = 1

            # 在中心坐标字典中增加或更新中心坐标出现的次数
            center_key = (center_x, center_y)
            if center_key in max_center_count:
                max_center_count[center_key] += 1
            else:
                max_center_count[center_key] = 1

            num_detected_objects += 1  # 记录识别到的物体数量

            if j == cfg.meantime:
                j = 0
                # 找到出现次数最多的标签
                max_label = max(label_counts, key=label_counts.get)
                label_true = max_label  # 将出现次数最多的标签赋给label_true
                print(f'平均出现最多标签为: {label_true}')

                # 找到出现次数最多的中心坐标
                max_center = max(max_center_count, key=max_center_count.get)
                center_x, center_y = max_center
                print(f'中心坐标为: ({center_x}, {center_y})')
                # 绘制标签框等操作
                # 这里你可以加入你的绘制代码
                # ...

                # 清空标签计数字典，以准备下一轮的计数
                label_time = label_time + 1
                label_counts = {}
                max_center_count = {}
            else:
                j += 1  # 增加j的值，以表示已经进行了一次识别

        return image, label_true, center_x, center_y, is_there_object, num_detected_objects, # 返回出现次数最多的标签